﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CDSBDemandControl.Model;
using CDSBDemandControl.Communication;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
using CDSBDemandControl.Configuration;

namespace CDSBDemandControl.Presenter
{
    [Serializable]
    public class DiscriminatorDemand:IDisposable
    {
        #region StatusColor
        
        private string LATE = "late";
        private string DEADLINE = "deadline";
        private string DEADLINECOMING = "deadlinecoming";
        private string AWAY = "away";
        private string NONE = "none";
        private string SUPERAVIT = "superAvit";
        private string DEFICIT = "deficit";
        private string TOTALIZADOR = "TotalFaturamento";

        #endregion

        #region Propriedades

        private int MinutesToRefresh;
        private string PlannedStateName;
        private string PlannedReasonName;
        private string LateItemsURL;
        private string ActiveControlUrL;
        private string DemandManagerName;
        private string PathToXmlFileDemands;
        private string PathToXmlFileBugs;
        private string PathToXmlfileOutOfDate;
        private string PathToXmlfileCodeReview;
        private string PathToXmlfileSolicitacoesSites;
        private string PathToXmlfileManagementTeamTasks;
        private IDiscriminatorDemand View;
        private List<string> StatusUnderDevelopment;
        private List<string> WorkItemsUnderDevelopment;
        private List<string> WorkItemsDeveloped;
        public IEnumerable<DeveloperModel> Developers;
        public IEnumerable<DeveloperModel> FocalPoints;
        public IEnumerable<DeveloperModel> Contributors;
        public List<string> TeamProjectsSinacor;
        public List<string> TeamProjectsIMercado;
        public List<string> TeamProjectsSiteBVMF;
        private List<DemandModel> DemandList;
        private List<DemandModel> DemandListOutOfDate;
        private List<DemandModel> CodeReviewReturns;
        private List<DemandModel> AllWorkItemsPeriod;        
        private List<DemandModel> ListaDisp;
        private DisponibilidadeModel modelAusencias;
        private List<DemandModel> BugList;
        private List<DemandModel> PrevisaoAlocacao;
        private List<DemandModel> SolicitacoesSites;
        private List<DemandModel> ManagementTeamTasks;

        private List<ScenarioModel> ScenariosAndTasks;
        private string WIScenariosAndTasksXMLPath;
        #endregion

        public DateTime DemandListLastUpdate {get; set;}
        public DateTime DemandListOutOfDateLastUpdate { get; set; }
        public DateTime DemandListCodeReviewLastUpdate { get; set; }
        public DateTime SolicitacoesSitesLastUpdate { get; set; }
        public DateTime ManagementTeamTasksLastUpdate { get; set; }
        public DateTime ScenariosAndTasksLastUpdate { get; set; }

        /// <summary>
        /// Contrutor da Presenter;
        /// Ivoca métodos para consultar:
        /// - Nome do Servidor do TFS;
        /// - Lista de Desenvolvedores;
        /// - Lista de Team Projects por projeto;
        /// - Lista de Status em desenvolvimento;
        /// - Lista de Work Items tratados pelo desenvolvimento;
        /// - Nome do Gestor de Demanda;
        /// </summary>
        /// <param name="view"></param>
        public DiscriminatorDemand(IDiscriminatorDemand view)
        {
            this.View = view;
            this.DemandList = null;
            this.DemandListOutOfDate = null;
            this.LoadConfigurations();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="view"></param>
        public void ResetView(IDiscriminatorDemand view)
        {
            this.View = view;
        }

        private void LoadDevelopers() 
        {
            List<DeveloperModel> Contributors = ConfigManager.GetContributors();

            this.Developers = from Contributor in Contributors where Contributor.Mission == Mission.Developer || (Contributor.Mission == Mission.Leader && !Contributor.DeveloperTeam.Contains("Gestão")) select Contributor;
            this.FocalPoints = from Contributor in Contributors where Contributor.Mission == Mission.FocalPoint || (Contributor.Mission == Mission.Leader && Contributor.DeveloperTeam.Contains("Gestão")) select Contributor; 
        }

        private void LoadConfigurations()
        {
            this.LoadDevelopers();
            this.LoadContributors();
            this.LateItemsURL = ConfigManager.GetLateItemsURL();
            this.MinutesToRefresh = ConfigManager.GetMinutesToRefresh();
            this.MinutesToRefresh = ConfigManager.GetMinutesToRefresh();
            this.ActiveControlUrL = ConfigManager.GetActiveControlUrL();
            this.PlannedStateName = ConfigManager.GetPlannedStateName();
            this.PlannedReasonName = ConfigManager.GetPlannedReasonName();
            this.DemandManagerName = ConfigManager.GetDemandManagerName();
            this.PathToXmlFileDemands = ConfigManager.GetWIPendingXMLPath();
            this.PathToXmlFileBugs = ConfigManager.GetBugsLastMonthXMLPath();
            this.WorkItemsDeveloped = ConfigManager.GetWorkItemsDeveloped();
            this.TeamProjectsSinacor = ConfigManager.GetTeamProjectsSinacor();
            this.PathToXmlfileOutOfDate = ConfigManager.GetWIOutOfDateXMLPath();
            this.TeamProjectsIMercado = ConfigManager.GetTeamProjectsIMercado();
            this.TeamProjectsSiteBVMF = ConfigManager.GetTeamProjectsSiteBVMF();
            this.StatusUnderDevelopment = ConfigManager.GetStatusUnderDevelopment();
            this.PathToXmlfileCodeReview = ConfigManager.GetWIWithCodeReviewXMLPath();
            this.PathToXmlfileSolicitacoesSites = ConfigManager.GetSolicitacoesSitesXMLPath();
            this.PathToXmlfileManagementTeamTasks = ConfigManager.GetManagementTeamTasksXMLPath();
            this.WIScenariosAndTasksXMLPath = ConfigManager.GetWIScenariosAndTasksXMLPath();
            this.WorkItemsUnderDevelopment = ConfigManager.GetWorkItemsUnderDevelopment();
        }

        private void LoadContributors()
        {
            Contributors = ConfigManager.GetContributors();
        }

        #region Esteira

        public bool CheckExistsWithin(string project, string TeamProject)
        {
            bool retorno = false;

            if (TeamProject == "TeamProjectsSinacor")
            {
                retorno = project.CheckExistsWithin(this.TeamProjectsSinacor);
            }
            else
            {
                if (TeamProject == "TeamProjectsIMercado")
                    retorno = project.CheckExistsWithin(this.TeamProjectsIMercado);
                else
                {
                    if (TeamProject == "TeamProjectsSiteBVMF")
                        retorno = project.CheckExistsWithin(this.TeamProjectsSiteBVMF);
                }
            }

            return retorno;
        }

        /// <summary>
        /// Lista Esteira de desenvolvimento
        /// </summary>
        /// <param name="projeto">Enum do Projeto que será o filtro da esteira</param>
        public void ListWorkItensIndevelopment(FiltroProjeto projeto)
        {
            this.GetDemandListFromServer();

            List<string> notAssignedTo = new List<string>();
            
            //Gestão de Portifólio
            notAssignedTo.Add("Camila Daiani Silva");
            notAssignedTo.Add("Glaucia Arie Kuma");
            notAssignedTo.Add("Marcelo de Almeida Pacheco");
            notAssignedTo.Add("Ricardo Divino Custodio");
            notAssignedTo.Add("Rodrigo Sanches Pena");
            
            //Suporte 3º nível
            notAssignedTo.Add("Ludmilla Modesto");
            notAssignedTo.Add("Marcelo Luis Prudente do Amaral");
            
            //Fábrica 7COMm
            notAssignedTo.Add("Ubiratan Radanovic Vieira");

            IEnumerable<DemandModel> Workitems = new List<DemandModel>();            

            switch (projeto)
            {
                case FiltroProjeto.Sinacor:
                    // Todos os workItens na esteira do projeto Sinacor
                    Workitems = from WorkItem in this.DemandList
                                where ((WorkItem.State != "Em Fila" && WorkItem.WorkItemType == "TaskDesenv") || (WorkItem.WorkItemType != "TaskDesenv" && WorkItem.AssignedTo.CheckExistsWithin(this.Contributors.ToNameList())))
                                    && WorkItem.Project.CheckExistsWithin(this.TeamProjectsSinacor)
                                    && (WorkItem.Origin != EnumOrigin.Producao && WorkItem.Origin != EnumOrigin.Corretora && WorkItem.Origin != EnumOrigin.Corretoras)
                                    && (!notAssignedTo.Contains(WorkItem.AssignedTo))
                                orderby
                                    WorkItem.WorkItemType descending, WorkItem.EstimatedConclude ascending, WorkItem.State ascending
                                select
                                    WorkItem;
                    break;
                case FiltroProjeto.iMercado:
                    // Todos os workItens na esteira  do projeto iMercado
                    Workitems = from WorkItem in this.DemandList
                                where (((WorkItem.State != "Em Fila" && WorkItem.WorkItemType == "TaskDesenv") || (WorkItem.WorkItemType != "TaskDesenv" && WorkItem.AssignedTo.CheckExistsWithin(this.Contributors.ToNameList())))
                                    && WorkItem.Project.CheckExistsWithin(this.TeamProjectsIMercado))
                                    && (!notAssignedTo.Contains(WorkItem.AssignedTo))
                                orderby
                                    WorkItem.WorkItemType descending, WorkItem.EstimatedConclude ascending, WorkItem.State ascending
                                select
                                    WorkItem;
                    break;
                case FiltroProjeto.SiteBVMF:
                    // Todos os workItens na esteira do projeto SiteBVMF
                    Workitems = from WorkItem in this.DemandList
                                where ((WorkItem.State != "Em Fila" && WorkItem.WorkItemType == "TaskDesenv") || (WorkItem.WorkItemType != "TaskDesenv" && WorkItem.AssignedTo.CheckExistsWithin(this.Contributors.ToNameList())))
                                    && WorkItem.Project.CheckExistsWithin(this.TeamProjectsSiteBVMF)
                                    && (WorkItem.Origin != EnumOrigin.Producao && WorkItem.Origin != EnumOrigin.Corretora && WorkItem.Origin != EnumOrigin.Corretoras)
                                    && (!notAssignedTo.Contains(WorkItem.AssignedTo))
                                orderby
                                    WorkItem.WorkItemType descending, WorkItem.EstimatedConclude ascending, WorkItem.State ascending
                                select
                                    WorkItem;
                    break;
                case FiltroProjeto.Todos:
                    // Todos os workItens na esteira independente de projeto
                    Workitems = from WorkItem in this.DemandList
                                where
                                (
                                (WorkItem.State != "Em Fila" && WorkItem.WorkItemType == "TaskDesenv")
                                ||
                                (WorkItem.WorkItemType != "TaskDesenv" && WorkItem.AssignedTo.CheckExistsWithin(this.Contributors.ToNameList()))
                                )
                                
                                &&
                                (WorkItem.Origin != EnumOrigin.Producao && WorkItem.Origin != EnumOrigin.Corretora && WorkItem.Origin != EnumOrigin.Corretoras)
                                && (!notAssignedTo.Contains(WorkItem.AssignedTo))
                                orderby
                                    WorkItem.WorkItemType descending, WorkItem.EstimatedConclude ascending, WorkItem.State ascending
                                select
                                    WorkItem;
                    break;
            }

            this.ApplyMatRules(Workitems);

            // Chama o método da View para exibir a esteira de Demandas por projeto
            this.View.ExibirEsteira(Workitems);
        }

        public void ListBugs()
        {
            this.GetBugListFromServer();
            this.View.ExibirBugsdeProducaoUltimoMes(BugList);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="workItems"></param>
        public void ApplyMatRules(IEnumerable<DemandModel> workItems)
        {
            DateTime DayAfter = DateTime.Now.GetdaysAfter(3);
            DateTime Today = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);

            foreach (DemandModel WorkItem in workItems)
            {
                WorkItem.Responsible = (WorkItem.WorkItemType == "TaskDesenv" || WorkItem.WorkItemType == "Task") ? WorkItem.CreatedBy + " / " + WorkItem.AssignedTo : WorkItem.AssignedTo;
                SetDemandStatusColor(WorkItem, Today, DayAfter);
                VerifyDevelopingOrPlanned(WorkItem, Today);
                CreateLinksToActivityControl(WorkItem);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private void CheckPlanningtask(DemandModel demand)
        {
            int PlanningHour = demand.EstimatedHours;

            DateTime EstimatedConclude = demand.EstimatedConclude.HasValue ? demand.EstimatedConclude.Value.Date : DateTime.Now.Date;

            int BusinessHours = 0;

            if (demand.EstimatedStart.HasValue && demand.EstimatedStart.Value.Date == DateTime.Now.Date && DateTime.Now.Hour < 11)
            {
                BusinessHours = DateTime.Now.Date.GetBusinessHoursUntil(demand.EstimatedConclude.Value);
            }
            else
            {
                BusinessHours = DateTime.Now.Date.AddDays(1).GetBusinessHoursUntil(demand.EstimatedConclude.HasValue ? demand.EstimatedConclude.Value : DateTime.Now.Date);
            }

            if (!demand.Start.HasValue && (BusinessHours < PlanningHour))
            {
                if (EstimatedConclude < DateTime.Now.Date)
                    demand.PlanningStateRemarks = "A tarefa já deveria ter terminado e ainda não começou.";
                else
                    demand.PlanningStateRemarks = String.Format(ConfigManager.GetErrorOBS(), EstimatedConclude.ToShortDateString(), demand.EstimatedHours);

                demand.PlanningStateImg = ConfigManager.GetErrorIcon();
            }
            else if (!demand.Start.HasValue)
            {
                demand.PlanningStateRemarks = ConfigManager.GetAttentionOBS();
                demand.PlanningStateImg = ConfigManager.GetAttentionIcon();
            }
            else
            {
                demand.PlanningStateRemarks = String.Empty;
                demand.PlanningStateImg = String.Empty;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private int CheckBusinessHours(DemandModel demand)
        {
            int Hours = 0;

            DateTime CheckDay = (demand.EstimatedStart.HasValue && demand.EstimatedStart.Value.Date == DateTime.Now.Date && DateTime.Now.Hour < 11) ? DateTime.Now.Date.AddDays(1) : DateTime.Now.Date;

            while (CheckDay <= (demand.EstimatedConclude.HasValue ? demand.EstimatedConclude : DateTime.Now.Date))
            {
                if (CheckDay.DayOfWeek != DayOfWeek.Saturday && CheckDay.DayOfWeek != DayOfWeek.Sunday)
                {
                    Hours += 8;
                }

                CheckDay = CheckDay.AddDays(1);
            }

            return Hours;
        }   

        #endregion

        #region Verificações

        private bool XMLNeedsToBeUpdated(string xmlPath, Visao witchXml)
        {
            DateTime PageLastUpdate = DateTime.MinValue;

            if (witchXml == Visao.Fila)
            {
                PageLastUpdate = DemandListLastUpdate;
            }
            else if (witchXml == Visao.Atrasos)
            {
                PageLastUpdate = DemandListOutOfDateLastUpdate;
            }
            else if (witchXml == Visao.Codereview)
            {
                PageLastUpdate = DemandListCodeReviewLastUpdate;
            }

            DateTime XMLLastRecorder = XMLDemandAccess.GetFileDate(xmlPath);

            if (PageLastUpdate.AddMinutes(this.MinutesToRefresh) < XMLLastRecorder)
                return true;
            else
                return false;
        }

        #endregion

        #region Busca de dados

        /// <summary>
        /// Popula a lista de Demandas.
        /// </summary>
        private void GetDemandListFromServer()
        {
            if (this.DemandList == null || this.XMLNeedsToBeUpdated(PathToXmlFileDemands,Visao.Fila))
            {
                this.DemandList = XMLDemandAccess.GetDemandCollectionFromXML(PathToXmlFileDemands);
                this.DemandListLastUpdate = XMLDemandAccess.GetFileDate(PathToXmlFileDemands);
            }
        }

        /// <summary>
        /// GetDemandListFromServer
        /// </summary>
        private void GetBugListFromServer()
        {
            if (this.BugList == null)
            {
                this.BugList = XMLDemandAccess.GetBugCollectionFromXML(PathToXmlFileBugs);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private void GetDemandListOutOfDateFromServer()
        {
            if (this.DemandListOutOfDate == null || this.XMLNeedsToBeUpdated(PathToXmlfileOutOfDate,Visao.Atrasos))
            {
                this.DemandListOutOfDate = this.CheckDaysLate(XMLDemandAccess.GetDemandCollectionFromXML(PathToXmlfileOutOfDate));
                this.DemandListOutOfDateLastUpdate = XMLDemandAccess.GetFileDate(PathToXmlfileOutOfDate);
            }
        }        

        /// <summary>
        /// 
        /// </summary>
        private void GetCodeReviewReturnsFromServer()
        {
            if (this.CodeReviewReturns == null || this.XMLNeedsToBeUpdated(PathToXmlfileCodeReview, Visao.Codereview))
            {
                this.CodeReviewReturns = XMLDemandAccess.GetDemandCollectionFromXML(PathToXmlfileCodeReview);

                this.DemandListCodeReviewLastUpdate = XMLDemandAccess.GetFileDate(PathToXmlfileCodeReview);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private void GetAllWorkItemsPeriodFromServer()
        {
            if (this.AllWorkItemsPeriod == null)
            {
                this.AllWorkItemsPeriod = XMLDemandAccess.GetDemandCollectionFromXML(ConfigManager.GetAllWIPeriodXMLPath());
                this.DemandListLastUpdate = XMLDemandAccess.GetFileDate(PathToXmlfileCodeReview);
            }
        }

        #endregion

        #region Métodos da Fila

        /// <summary>
        /// Lista a Fila de desenvolvimento por projeto
        /// </summary>
        /// <param name="projeto">Enum do Projeto que será o filtro da fila</param>
        public void ListWorkItensRow(FiltroProjeto projeto)
        {
            this.GetDemandListFromServer();

            IEnumerable<DemandModel> Workitems = new List<DemandModel>();

            switch (projeto)
            {
                case FiltroProjeto.Sinacor:
                    // Todos os workItens em fila do Sinacor
                    Workitems = from WorkItem in this.DemandList
                                where
                                    ((WorkItem.State == "Em Fila" && WorkItem.WorkItemType == "TaskDesenv") || (WorkItem.AssignedTo.Equals(this.DemandManagerName) && WorkItem.WorkItemType != "TaskDesenv"))
                                    && WorkItem.Project.CheckExistsWithin(this.TeamProjectsSinacor) && !WorkItem.AssignedTo.Equals("Danilo Mansi Medeiros")                                     
                                orderby WorkItem.DataIncFila ascending
                                select WorkItem;
                    break;
                case FiltroProjeto.iMercado:
                    // Todos os workItens em fila do iMercado
                    Workitems = from WorkItem in this.DemandList
                                where
                                    ((WorkItem.State == "Em Fila" && WorkItem.WorkItemType == "TaskDesenv") || (WorkItem.AssignedTo.Equals(this.DemandManagerName) && WorkItem.WorkItemType != "TaskDesenv"))
                                    && WorkItem.Project.CheckExistsWithin(this.TeamProjectsIMercado) && !WorkItem.AssignedTo.Equals("Danilo Mansi Medeiros")                                     
                                orderby WorkItem.DataIncFila ascending
                                select WorkItem;
                    break;
                case FiltroProjeto.SiteBVMF:
                    // Todos os workItens em fila do SiteBVMF
                    Workitems = from WorkItem in this.DemandList
                                where
                                    (
                                        (
                                            WorkItem.State == "Em Fila" 
                                            && 
                                            WorkItem.WorkItemType == "TaskDesenv"
                                        ) 
                                        || 
                                        (
                                            WorkItem.AssignedTo.Equals(this.DemandManagerName) 
                                            && 
                                            WorkItem.WorkItemType != "TaskDesenv"
                                        )
                                    )
                                    && 
                                            WorkItem.Project.CheckExistsWithin(this.TeamProjectsSiteBVMF)
                                    &&
                                            !WorkItem.AssignedTo.Equals("Danilo Mansi Medeiros")                                     
                                orderby WorkItem.DataIncFila ascending
                                select WorkItem;
                    break;
                case FiltroProjeto.Todos:
                    // Todos os workItens em fila independente de projeto
                    Workitems = from WorkItem in this.DemandList
                                where
                                        (
                                (
                                    (
                                        WorkItem.State == "Em Fila" && 
                                        WorkItem.WorkItemType == "TaskDesenv"
                                    ) 
                                    || 
                                    (
                                        WorkItem.AssignedTo.Equals(this.DemandManagerName) 
                                        && 
                                        WorkItem.WorkItemType != "TaskDesenv"
                                    )
                                )
                                    &&
                                    (
                                        !WorkItem.AssignedTo.Equals("Danilo Mansi Medeiros") 
                                    )
                                        )
                                orderby WorkItem.DataIncFila ascending
                                select WorkItem;
                    break;
            }

            List<DemandModel> newList = new List<DemandModel>(this.DemandList.Count);

            this.DemandList.ForEach((item) =>
            {
                switch (projeto)
                {
                    case FiltroProjeto.Sinacor:
                        if (item.State == "Em Codificacao" && item.AssignedTo.Equals("Ubiratan Radanovic Vieira") && item.Project.CheckExistsWithin(this.TeamProjectsSinacor))
                            newList.Add(new DemandModel(item, "Em Avaliação", "Enviada para Fábrica Externa"));
                        break;
                    case FiltroProjeto.iMercado:
                        if (item.State == "Em Codificacao" && item.AssignedTo.Equals("Ubiratan Radanovic Vieira") && item.Project.CheckExistsWithin(this.TeamProjectsIMercado))
                            newList.Add(new DemandModel(item, "Em Avaliação", "Enviada para Fábrica Externa"));
                        break;
                    case FiltroProjeto.SiteBVMF:
                        if (item.State == "Em Codificacao" && item.AssignedTo.Equals("Ubiratan Radanovic Vieira") && item.Project.CheckExistsWithin(this.TeamProjectsSiteBVMF))
                            newList.Add(new DemandModel(item, "Em Avaliação", "Enviada para Fábrica Externa"));
                        break;
                    case FiltroProjeto.Todos:
                        if (item.State == "Em Codificacao" && item.AssignedTo.Equals("Ubiratan Radanovic Vieira"))
                            newList.Add(new DemandModel(item, "Em Avaliação", "Enviada para Fábrica Externa"));
                        break;                    
                }
            });               
            
            Workitems = Workitems.Union<DemandModel>(newList);

            this.ApplyRowRules(Workitems);
            this.View.ExibirFila(Workitems);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="workItems"></param>
        public void ApplyRowRules(IEnumerable<DemandModel> workItems)
        {
            DateTime Today = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);

            foreach (DemandModel WorkItem in workItems)
            {
                SetRowStatusColor(WorkItem, Today);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="workItem"></param>
        /// <param name="today"></param>
        /// <param name="dayAfter"></param>
        private void SetRowStatusColor(DemandModel workItem, DateTime today)
        {
            // Previsão de início não informada ou está atrasada. LATE
            if (!workItem.EstimatedStart.HasValue || workItem.EstimatedStart.Value <= today)
            {
                workItem.StatusColor = LATE; // Vermelho
            }
            // Previsão de início está entre hoje e amanhã
            else if (workItem.EstimatedStart.Value <= today.GetdaysAfter(2))
            {
                workItem.StatusColor = DEADLINE; // Laranja
            }
            // Previsão de início está a menos de 7 dias
            else if (workItem.EstimatedStart.Value <= today.GetdaysAfter(7))
            {
                workItem.StatusColor = DEADLINECOMING; // Amarelo
            }
            // Previsão de início está a mais de 7 dias
            else if (workItem.EstimatedStart.Value > today.GetdaysAfter(7))
            {
                workItem.StatusColor = AWAY; // Verde
            }
        }

        #endregion

        #region Métodos da Esteira

        /// <summary>
        /// 
        /// </summary>
        /// <param name="workItem"></param>
        /// <param name="today"></param>
        /// <param name="dayAfter"></param>
        private void SetDemandStatusColor(DemandModel workItem, DateTime today, DateTime dayAfter)
        {
            // Se está atrasado
            if (workItem.EstimatedConclude < today)
            {
                workItem.StatusColor = LATE;
            }
            // Se termina hoje
            else if (workItem.EstimatedConclude == today || workItem.EstimatedConclude == today.AddDays(1))
            {
                workItem.StatusColor = DEADLINE;
            }
            // Se está a no máximo 5 dias do fim
            else if (workItem.EstimatedConclude <= dayAfter)
            {
                workItem.StatusColor = DEADLINECOMING;
            }
            // Sem Data de Conclusão Definida
            else if (workItem.EstimatedConclude == null)
            {
                workItem.StatusColor = NONE;
            }
            // No Prazo
            else
            {
                workItem.StatusColor = AWAY;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Tasks"></param>
        /// <param name="isCodeReviewCollection"></param>
        private void SetDeveloperOfEachTask(IEnumerable<DemandModel> Tasks, bool isCodeReviewCollection) 
        {
            foreach (DemandModel Task in Tasks)
            {
                DeveloperModel Developer = FindDeveloperOf(Task.Revision);

                if (Developer != null)
                {
                    Task.Responsible = Developer.DeveloperName;

                    Developer.TasksImplemented++;

                    if (isCodeReviewCollection) Developer.TasksDisapprovedInCodeReview++;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private void CreateLinksToActivityControl(DemandModel workItem)
        {
            if (workItem.WorkItemType == "TaskDesenv" || workItem.WorkItemType == "Task")
            {
                workItem.ActiveControlUrL = String.Format(this.ActiveControlUrL, workItem.ID);
            }
            else
            {
                workItem.ActiveControlUrL = "";
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="workItem"></param>
        private void VerifyDevelopingOrPlanned(DemandModel workItem, DateTime startDate) 
        {
            if (!workItem.Start.HasValue || workItem.EstimatedStart > startDate)
            {
                workItem.State = this.PlannedStateName;
                workItem.Reason = this.PlannedReasonName;
                CheckPlanningtask(workItem);
            }
        }

        #endregion

        #region Suporte 3º Nível

        public void ListProductionBugs() 
        {
            this.GetDemandListFromServer();
            IEnumerable<DemandModel> Workitems = from WorkItem in this.DemandList
                        where WorkItem.WorkItemType == "Bug" &&
                        (WorkItem.Origin == EnumOrigin.Producao || WorkItem.Origin == EnumOrigin.Corretora || WorkItem.Origin == EnumOrigin.Corretoras)
                        &&
                        (this.Contributors.ToList().Find(delegate (DeveloperModel md) { return md.DeveloperName == WorkItem.AssignedTo;}).DeveloperTeam == "Suporte 3º Nível")
                        orderby
                            WorkItem.Priority ascending, WorkItem.Gravity ascending
                        select
                            WorkItem;

            this.ApplyMatRules(Workitems);
            Workitems = Workitems.ToList().FindAll(delegate(DemandModel dem)
            {
                DeveloperModel md = this.Developers.ToList().Find(delegate(DeveloperModel dev)
                {
                    return dev.DeveloperName == dem.AssignedTo;
                }
                );
                return (md == null || !(md.Remarks.Trim().ToLower().Contains("naolistar")));
            }
            );

            // Chama o método da View para exibir os Bugs de Produção por projeto
            this.View.ExibirBugsdeProducao(Workitems);
        }

        #endregion

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="workItem"></param>
        ///// <param name="today"></param>
        ///// <param name="dayAfter"></param>
        //private void SetDeveloperStatusColor(DeveloperModel developer, DateTime refDay)
        //{
        //    // Se a última data alocada é menor que a data de referência ou (é hoje ou hoje +1)
        //    if (developer.FreeDate < refDay || (developer.FreeDate == refDay || developer.FreeDate <= refDay.GetdaysAfter(1)))
        //    {
        //        developer.StatusColor = LATE;
        //    }
        //    // Se a última data alocada está entre depois de amanhã ou depois de amanhã+1
        //    else if (developer.FreeDate <= refDay.GetdaysAfter(3))
        //    {
        //        developer.StatusColor = DEADLINE;
        //    }
        //    // Se a última data alocada é até 7 dias.
        //    else if (developer.FreeDate <= refDay.GetdaysAfter(7))
        //    {
        //        developer.StatusColor = DEADLINECOMING;
        //    }
        //    // Com Atividades para mais de 7 dias;
        //    else
        //    {
        //        developer.StatusColor = AWAY;
        //    }
        //}

        #region Performance

        /// <summary>
        /// 
        /// </summary>
        public void MountRankingDelays(string reportType)
        {
            this.GetAllWorkItemsPeriodFromServer();
            this.GetDemandListOutOfDateFromServer();

            this.ClearPreviousRankings();

            this.GenerateDeveloperLeaderFocalPointData(reportType);

            List<DeveloperModel> DeveloperList = ConfiguraRecursosSuporte();

            IEnumerable<DeveloperModel> leaderList = from Developer in Developers where Developer.Mission == Mission.Leader && Developer.DeveloperName != "Rodrigo Sanches Pena" orderby Developer.DeveloperName ascending select Developer;
            IEnumerable<DeveloperModel> FocalPoints = from Developer in Contributors where Developer.Mission == Mission.FocalPoint orderby Developer.DeveloperName ascending select Developer;

            this.View.ExibirRanking(DeveloperList, leaderList, FocalPoints);
        }

        private List<DeveloperModel> ConfiguraRecursosSuporte()
        {
            List<DeveloperModel> DeveloperList = new List<DeveloperModel>();

            List<string> devTimeA = new List<string>() { "Vanessa Fernandes de Moraes", "Andre Pereira da Silva", "Marcelo Luis Prudente do Amaral" };
            List<string> devTimeB = new List<string>() { "Fabio Massamitsu Minamikawa", "Joao Paulo Gregório Pontes" };

            Developers.ToList().ForEach(delegate(DeveloperModel md)
            {
                if (md.Mission == Mission.Developer)
                {
                    if (devTimeA.Contains(md.DeveloperName))
                    {
                        DeveloperList.Add(new DeveloperModel(md.DeveloperName, "TimeA", md.Mission, md.StartFreeDaysPaid, md.FinishFreeDaysPaid, md.Remarks, md.VH, null, md.TasksImplemented, md.TasksReleasedLate));
                    }
                    else
                        if (devTimeB.Contains(md.DeveloperName))
                        {
                            DeveloperList.Add(new DeveloperModel(md.DeveloperName, "TimeB", md.Mission, md.StartFreeDaysPaid, md.FinishFreeDaysPaid, md.Remarks, md.VH, null, md.TasksImplemented, md.TasksReleasedLate));
                        }
                        else
                        {
                            DeveloperList.Add(new DeveloperModel(md.DeveloperName, md.DeveloperTeam, md.Mission, md.StartFreeDaysPaid, md.FinishFreeDaysPaid, md.Remarks, md.VH, null, md.TasksImplemented, md.TasksReleasedLate));
                        }
                }
            });
            return DeveloperList;
        }

        private void GenerateDeveloperLeaderFocalPointData(string reportType)
        {
            // Retira da coleção as tarefas em atraso, em fila ou simplismente ativas.
            List<DemandModel> DemandsDeliveredOnTime = (from WorkItem in this.AllWorkItemsPeriod
                                                        where
                                                            WorkItem.CheckExistsWithin(DemandListOutOfDate) == false
                                                            && WorkItem.State == "Concluida"                                                            
                                                        select WorkItem).ToList<DemandModel>();

            if (string.IsNullOrEmpty(reportType))
            {
                DemandsDeliveredOnTime = (from WorkItem in DemandsDeliveredOnTime
                                          where
                                            WorkItem.Conclude.HasValue && WorkItem.Conclude.Value.Date >= DateTime.Parse(ConfigManager.GetPeriodStartDate()).Date
                                          select WorkItem).ToList<DemandModel>();
            }
            else
                if (reportType == "semestral")
                {
                    DateTime dt = DateTime.Parse(ConfigManager.GetPeriodStartDate());
                    dt = new DateTime(dt.Year, dt.Month,1);
                    dt = dt.AddMonths(-6);

                    DemandsDeliveredOnTime = (from WorkItem in DemandsDeliveredOnTime
                                              where
                                                WorkItem.Conclude.HasValue && WorkItem.Conclude.Value.Date >= dt.Date
                                              select WorkItem).ToList<DemandModel>();
                }

            //Entregues na data
            foreach (DemandModel md in DemandsDeliveredOnTime)
            {
                DeveloperModel Developer = null;
                Developer = this.FindDeveloperOf(md.Revision);

                if (Developer != null)
                {
                    Developer.TasksImplemented += 1;

                    if (Developer.DeveloperTeam != "timeScrum")
                    {
                        DeveloperModel Leader = null;

                        if (Developer.DeveloperTeam == "Suporte 3º Nível")
                        {
                            Leader = this.FindLeaderOf(ConfiguraRecursosSuporte().Find(delegate(DeveloperModel col)
                            { return col.DeveloperName == Developer.DeveloperName; }).DeveloperTeam);
                        }
                        else
                            Leader = this.FindLeaderOf(Developer.DeveloperTeam);

                        if (Leader != null)
                            Leader.TasksImplemented += 1;

                        DeveloperModel FocalPoint = this.FindFocalPointOf(md.Project);
                        if (FocalPoint != null) FocalPoint.TasksImplemented += 1;
                    }
                }
            }

            //Atrasadas

            List<DemandModel> DemandListOutOfDateInterna = null;

            if (string.IsNullOrEmpty(reportType))
            {
                DemandListOutOfDateInterna = (from WorkItem in this.DemandListOutOfDate
                                          where
                                            WorkItem.State == "Concluida" &&
                                            WorkItem.Conclude.HasValue && WorkItem.Conclude.Value.Date >= DateTime.Parse(ConfigManager.GetPeriodStartDate()).Date
                                          select WorkItem).ToList<DemandModel>();
            }
            else
                if (reportType == "semestral")
                {
                    DateTime dt = DateTime.Parse(ConfigManager.GetPeriodStartDate());
                    dt = new DateTime(dt.Year, dt.Month, 1);
                    dt = dt.AddMonths(-6);

                    DemandListOutOfDateInterna = (from WorkItem in this.DemandListOutOfDate
                                              where
                                                WorkItem.State == "Concluida" &&
                                                WorkItem.Conclude.HasValue && WorkItem.Conclude.Value.Date >= dt.Date
                                              select WorkItem).ToList<DemandModel>();
                }

            foreach (DemandModel md in DemandListOutOfDateInterna)
            {
                DeveloperModel Developer = null;
                Developer = this.FindDeveloperOf(md.Revision);

                if (Developer != null)
                {
                    Developer.TasksImplemented += 1;
                    Developer.TasksReleasedLate += 1;

                    if (Developer.DeveloperTeam != "timeScrum")
                    {

                        DeveloperModel Leader = null;

                        if (Developer.DeveloperTeam == "Suporte 3º Nível")
                        {
                            Leader = this.FindLeaderOf(ConfiguraRecursosSuporte().Find(delegate(DeveloperModel col)
                            { return col.DeveloperName == Developer.DeveloperName; }).DeveloperTeam);
                        }
                        else
                            Leader = this.FindLeaderOf(Developer.DeveloperTeam);

                        if (Leader != null)
                        {
                            Leader.TasksImplemented += 1;
                            Leader.TasksReleasedLate += 1;
                        }

                        DeveloperModel FocalPoint = this.FindFocalPointOf(md.Project);
                        if (FocalPoint != null)
                        {
                            FocalPoint.TasksImplemented += 1;
                            FocalPoint.TasksReleasedLate += 1;
                        }
                    }
                }
            }    
            
        }

        public DeveloperModel FindDeveloperOf(DemandCollection revisions)
        {
            List <RevisionModel> revs = revisions.Cast<RevisionModel>().OrderBy(rev => rev.ChangedDate).ToList();

            string developerName = string.Empty;

            for (int i = (revs.Count - 1); i >= 0; i--)
            {
                RevisionModel r = revs[i];
                
                if ((r.State.Equals("Em Teste") || r.State.Equals("Em Codificacao")) && this.Developers.GetDeveloperByName(r.AssignedTo) != null)
                {
                    developerName = r.AssignedTo;
                    
                    if (r.State.Equals("Em Codificacao") || developerName != string.Empty) break;
                }
            }

            return this.Developers.GetDeveloperByName(developerName);
            
        }

        private DeveloperModel FindFocalPointOf(string project)
        {
            return this.Contributors.GetFocalPointByProject(project);            
        }

        private DeveloperModel FindLeaderOf(string team)
        {
            return this.Developers.GetLeaderByTeam(team);
        }

        /// <summary>
        /// 
        /// </summary>
        private void ClearPreviousRankings()
        {
            this.Developers.ClearRanking();
            this.FocalPoints.ClearRanking();
        }

        #endregion

        #region Pontualidade

        #endregion

        #region Faturamento

        public void GenerateFactoryWaitingList(FiltroFabrica filtroFabrica, FiltroProjeto filtroProjeto, string requestingUser)
        {
            bool AllowsShow = this.CheckPermission(requestingUser);

            List<BillingModel> Billing = new List<BillingModel>();

            this.GetDemandListFromServer();

            List<DemandModel> AllTasks = (from Task in this.DemandList
                                          where Task.State == "Em Codificacao" 
                                          && Task.AssignedTo.Equals("Ubiratan Radanovic Vieira")
                                          select Task).ToList<DemandModel>();

            if (AllowsShow)
            {
                #region Se tiver permissão monta o Faturamento

                foreach (DemandModel Task in AllTasks)
                {
                    BillingModel BillingItem = new BillingModel();
                    DeveloperModel Developer = this.FindDeveloperOf(Task.Revision);

                    if (Developer != null)
                    {
                        BillingItem.Task = Task.ID + " - " + Task.Title;
                        BillingItem.Project = Task.Project;
                        BillingItem.Factory = Developer.DeveloperName.GetFactory(this.Developers);
                        BillingItem.Hourly = Developer.VH;
                        BillingItem.PredictedHours = Task.EstimatedHours;
                        //
                        if (BillingItem.Hourly == 50)
                        {
                            BillingItem.EstimatedValue = 52.63M * BillingItem.PredictedHours;
                            BillingItem.UsedValue = 52.63M * BillingItem.UsedHours;
                        }
                        else
                        {
                            BillingItem.EstimatedValue = BillingItem.Hourly * BillingItem.PredictedHours;
                            BillingItem.UsedValue = BillingItem.Hourly * BillingItem.UsedHours;
                        }
                        //
                        BillingItem.UsedHours = Task.UsedHours;
                        BillingItem.Deviation = BillingItem.EstimatedValue - BillingItem.UsedValue;
                        BillingItem.State = Task.State;
                        BillingItem.EstimatedStart = Task.EstimatedStart;
                        BillingItem.EstimatedConclude = Task.EstimatedConclude;

                        Billing.Add(BillingItem);
                    }
                }

                #endregion
            }
            else
            {
                #region Se não tiver não monta o Faturamento

                foreach (DemandModel Task in AllTasks)
                {
                    BillingModel BillingItem = new BillingModel();
                    DeveloperModel Developer = this.FindDeveloperOf(Task.Revision);

                    if (Developer != null)
                    {
                        BillingItem.Task = Task.ID + " - " + Task.Title;
                        BillingItem.Project = Task.Project;
                        BillingItem.Factory = Developer.DeveloperName.GetFactory(this.Developers);
                        BillingItem.PredictedHours = Task.EstimatedHours;
                        BillingItem.UsedHours = Task.UsedHours;

                        BillingItem.State = Task.State;
                        BillingItem.EstimatedStart = Task.EstimatedStart;
                        BillingItem.EstimatedConclude = Task.EstimatedConclude;

                        Billing.Add(BillingItem);
                    }
                }

                #endregion
            }

            Billing = (from BillingItem in Billing where BillingItem.Factory.CheckFilterFactory(filtroFabrica) && BillingItem.Project.CheckFilterProject(filtroProjeto) select BillingItem).ToList<BillingModel>();

            this.TotalBilling(Billing);

            this.View.ExibirFactoryWaitingList(Billing, AllowsShow);
        }

        public void GenerateRevenue(FiltroFabrica filtroFabrica, FiltroProjeto filtroProjeto,string requestingUser)
        {
            bool AllowsShow = this.CheckPermission(requestingUser);

            List<BillingModel> Billing = new List<BillingModel>();
            
            this.GetAllWorkItemsPeriodFromServer();

            List<DemandModel> AllTasks = (from Task in AllWorkItemsPeriod where 
                                              Task.State == "Concluida" 
                                          &&
                                              Task.Conclude.HasValue && Task.Conclude.Value.Date >= DateTime.Parse(ConfigManager.GetPeriodStartDate()).Date
                                          select Task).ToList<DemandModel>();
            if (AllowsShow)
            {
                #region Se tiver permissão monta o Faturamento

                foreach (DemandModel Task in AllTasks)
                {
                    BillingModel BillingItem = new BillingModel();
                    DeveloperModel Developer = this.FindDeveloperOf(Task.Revision);

                    if (Developer != null)
                    {
                        BillingItem.Task = Task.ID + " - " + Task.Title;
                        BillingItem.Project = Task.Project;

                        if (Developer.Mission == Mission.Developer)
                            BillingItem.Factory = Developer.DeveloperName.GetFactory(this.Developers);
                        else
                            BillingItem.Factory = "CDSB";

                        BillingItem.Hourly = Developer.VH;
                        BillingItem.PredictedHours = Task.EstimatedHours;
                        BillingItem.UsedHours = Task.UsedHours;
                        //
                        if (BillingItem.Hourly == 50)
                        {
                            BillingItem.EstimatedValue = 52.63M * BillingItem.PredictedHours;
                            BillingItem.UsedValue = 52.63M * BillingItem.UsedHours;
                        }
                        else
                        {
                            BillingItem.EstimatedValue = BillingItem.Hourly * BillingItem.PredictedHours;
                            BillingItem.UsedValue = BillingItem.Hourly * BillingItem.UsedHours;
                        }
                        //
                        BillingItem.Deviation = BillingItem.EstimatedValue - BillingItem.UsedValue;
                        BillingItem.State = Task.State;
                        BillingItem.EstimatedStart = Task.EstimatedStart;
                        BillingItem.EstimatedConclude = Task.EstimatedConclude;

                        Billing.Add(BillingItem);
                    }
                }

                #endregion
            }
            else
            {
                #region Se não tiver não monta o Faturamento
                
                foreach (DemandModel Task in AllTasks)
                {
                    BillingModel BillingItem = new BillingModel();
                    DeveloperModel Developer = this.FindDeveloperOf(Task.Revision);

                    if (Developer != null)
                    {
                        BillingItem.Task = Task.ID + " - " + Task.Title;
                        BillingItem.Project = Task.Project;
                        BillingItem.Factory = Developer.DeveloperName.GetFactory(this.Developers);
                        BillingItem.PredictedHours = Task.EstimatedHours;
                        BillingItem.UsedHours = Task.UsedHours;
                        BillingItem.State = Task.State;
                        BillingItem.EstimatedStart = Task.EstimatedStart;
                        BillingItem.EstimatedConclude = Task.EstimatedConclude;

                        Billing.Add(BillingItem);
                    }
                }

                #endregion
            }

            Billing = Billing.FindAll(delegate(BillingModel bil)
            {
                bool ftrFactory = bil.Factory.CheckFilterFactory(filtroFabrica);
                bool ftrProject = bil.Project.CheckFilterProject(filtroProjeto);

                return  (ftrFactory && ftrProject);
            }
            );

            this.TotalBilling(Billing);

            this.View.ExibirFaturamento(Billing, AllowsShow);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="requestingUser"></param>
        /// <returns></returns>
        public bool CheckPermission(string requestingUser)
        {
            return requestingUser.ToLower().CheckExistsWithin(ConfigManager.GetAllowedUserBilling());
        }

        private void TotalBilling(List<BillingModel> Billing) 
        {
            BillingModel Total = new BillingModel();
            
            Total.Task = "Total";
            Total.PredictedHours = (from BillingItem in Billing select BillingItem.PredictedHours).Sum();
            Total.UsedHours = (from BillingItem in Billing select BillingItem.UsedHours).Sum();
            Total.EstimatedValue = (from BillingItem in Billing select BillingItem.EstimatedValue).Sum();
            Total.UsedValue = (from BillingItem in Billing select BillingItem.UsedValue).Sum();
            Total.Deviation = (from BillingItem in Billing select BillingItem.Deviation).Sum();

            Total.DeviationColor = TOTALIZADOR;
            
            Billing.Add(Total);
        }

        #endregion

        #region Qualidade

        #endregion

        /// <summary>
        /// Altera informações de tasks implementadas e tasks atrasadas da coleção de pontos focal e desenvolvedores
        /// </summary>
        private void DiscriminateResponsibleForEachTask() 
        {
            // Retira da coleção as tarefas em atraso, em fila ou simplismente ativas.
            List<DemandModel> DemandsDeliveredOnTime = (from WorkItem in this.AllWorkItemsPeriod
                                                        where
                                                            WorkItem.CheckExistsWithin(DemandListOutOfDate) == false
                                                            && WorkItem.State == "Concluida"
                                                        select WorkItem).ToList<DemandModel>();

            // Pega o maior Count entre Itens atrasados e entregues.
            // Em vez de fazer dois foreach, verificar se o indice é menor que o cont das coleções, se for 
            // pega cara item e aplica a regra.
            for (int indice = 0; indice < DemandsDeliveredOnTime.Count<DemandModel>().ReturMore(DemandListOutOfDate.Count); indice++)
            {
                DeveloperModel Developer = null;
                DeveloperModel FocalPoint = null;

                //Verifica se o indice está dentro do range da coleção de tasks
                if (indice < DemandsDeliveredOnTime.Count)
                {
                    // Obtem o Desenvolvedor e o Ponto Focal
                    Developer = this.FindDeveloperOf(DemandsDeliveredOnTime[indice].Revision);
                    FocalPoint = this.GetFocalPointResponsible(DemandsDeliveredOnTime[indice].Revision);

                    string teste = Developer.DeveloperName;

                    // Soma uma atividade entregue para cada um
                    if (Developer != null) Developer.TasksImplemented += 1;
                    if (FocalPoint != null) FocalPoint.TasksImplemented += 1;
                }

                // Verifica se o indice está dentro do range da coleção
                if (indice < DemandListOutOfDate.Count)
                {
                    // Obtem o Desenvolvedor e o Ponto Focal
                    Developer = this.FindDeveloperOf(DemandListOutOfDate[indice].Revision);
                    FocalPoint = this.GetFocalPointResponsible(DemandListOutOfDate[indice].Revision);

                    // Soma uma atividade entregue para cada um
                    // Soma uma atividade em atraso para cada um
                    
                    if (Developer != null)
                    {
                        Developer.TasksImplemented += 1;
                        Developer.TasksReleasedLate += 1;
                        
                    }

                    if (FocalPoint != null)
                    {
                        FocalPoint.TasksImplemented += 1;
                        FocalPoint.TasksReleasedLate += 1;
                    }

                    // Soma a quantidade de dias de atraso da task para cada um.
                    Developer.DayPast += DemandListOutOfDate[indice].DaysPast;
                    FocalPoint.DayPast += DemandListOutOfDate[indice].DaysPast;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private void CountLeadersDelay()
        {
            foreach (DeveloperModel Leader in (from Developer in this.Developers where Developer.Mission == Mission.Leader select Developer))
            {
                if (Leader.DeveloperTeam == "VCoding")
                {
                    Leader.TasksImplemented = (from Developer in this.Developers where Developer.DeveloperTeam.Contains("VCoding") select Developer.TasksImplemented).Sum();
                    Leader.TasksReleasedLate = (from Developer in this.Developers where Developer.DeveloperTeam.Contains("VCoding") select Developer.TasksReleasedLate).Sum();
                }
                else 
                {
                    Leader.TasksImplemented = (from Developer in this.Developers where !Developer.DeveloperTeam.Contains("VCoding") select Developer.TasksImplemented).Sum();
                    Leader.TasksReleasedLate = (from Developer in this.Developers where !Developer.DeveloperTeam.Contains("VCoding") select Developer.TasksReleasedLate).Sum();
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private void CountLeadersCodeReview()
        {
            foreach (DeveloperModel Leader in (from Developer in this.Developers where Developer.Mission == Mission.Leader && Developer.DeveloperTeam.IndexOf("TDI") > -1 select Developer))
            {
                Leader.TasksDisapprovedInCodeReview = (from Developer in this.Developers where Developer.DeveloperTeam == Leader.DeveloperTeam select Developer.TasksDisapprovedInCodeReview).Sum();
            }
        }

        ///// <summary>
        ///// Retorna o desenvolvedor responsável pela task com base nas revisões da task.
        ///// </summary>
        ///// <param name="revisions">DemandCollection</param>
        //private DeveloperModel GetDeveloperResponsible(DemandCollection revisions)
        //{
        //    DeveloperModel retorno = null;

        //    // Pega a lista de revisões com o status em codificação, ordena por data de alteração e pega o primeiro da lista;
        //    // Ou seja, o último a ficar com a task em codificação é considerado o responsável pela task
        //    //RevisionModel Revision = (from Rev in revisions.Cast<RevisionModel>() where Rev.State == "Em Codificacao" && Rev.AssignedTo.CheckExistsWithin(this.Developers) orderby Rev.ChangedDate descending select Rev).First();

        //    var Revision = (from Rev in revisions.Cast<RevisionModel>() where Rev.State == "Em Codificacao" && Rev.AssignedTo.CheckExistsWithin(this.Developers) orderby Rev.ChangedDate descending select Rev);

        //    RevisionModel rev = null;

        //    if (Revision.Count() != 0)
        //    {
        //        rev = ((RevisionModel)(Revision.First()));
        //        retorno = this.Developers.GetDeveloperByName(rev.AssignedTo);
        //    }

        //    return retorno;

        //}

        /// <summary>
        /// Retorna o desenvolvedor responsável pela task com base nas revisões da task.
        /// </summary>
        /// <param name="revisions">DemandCollection</param>
        private DeveloperModel GetFocalPointResponsible(DemandCollection revisions)
        {
            // Pega a lista de revisões com o status Ativo, ordena por data de alteração e pega o primeiro da lista;
            // Ou seja, o último a ficar com a task como Ativo é considerado o responsável pela task
            RevisionModel Revision = (from Rev in revisions.Cast<RevisionModel>() where Rev.State == "Ativa" orderby Rev.ChangedDate descending select Rev).First();

            return this.FocalPoints.GetDeveloperByName(Revision.AssignedTo);
        }

        /// <summary>
        /// 
        /// </summary>
        public void ListWorkItemsOutOfDate() 
        {
            this.GetDemandListOutOfDateFromServer();

            List<DemandModel> AllTasks = (from Task in DemandListOutOfDate
                                          where
                                              !Task.Conclude.HasValue || Task.Conclude.Value.Date >= DateTime.Parse(ConfigManager.GetPeriodStartDate()).Date
                                          select Task).ToList<DemandModel>();

            CreateLinksToLateItens(AllTasks);

            IEnumerable<DemandModel> Pending = (IEnumerable<DemandModel>)(from Demand in AllTasks where Demand.State != "Concluida" orderby Demand.Conclude descending select Demand);
            IEnumerable<DemandModel> Conclude = (IEnumerable<DemandModel>)(from Demand in AllTasks where Demand.State == "Concluida" orderby Demand.Conclude descending select Demand);

            this.View.ExibirAtrasos(Pending,Conclude);
        }



        public void ListarPrevisaoAlocacao()
        {
            this.GetPrevisaoAlocacaoFromServer();

            PrevisaoAlocacao = PrevisaoAlocacao.OrderBy(task => task.Project).ToList();
                
            this.View.ExibirAlocacao(PrevisaoAlocacao);
        }

        /// <summary>
        /// 
        /// </summary>
        public void ListWitWithCodeReview()
        {
            this.GetAllWorkItemsPeriodFromServer();

            List<DemandModel> AllTasks = (from Task in AllWorkItemsPeriod
                                          where
                                              !Task.Conclude.HasValue  || Task.Conclude.Value.Date >= DateTime.Parse(ConfigManager.GetPeriodStartDate()).Date
                                          select Task).ToList<DemandModel>();

            this.GetCodeReviewReturnsFromServer();

            this.ClearPreviousRankings();

            IEnumerable<DemandModel> DemandsWithoutCodeReview = from WorkItem in AllTasks
                                                          where WorkItem.CheckExistsWithin(CodeReviewReturns) == false
                                                                && WorkItem.State == "Concluida" && WorkItem.WorkItemType == "TaskDesenv"
                                                                && WorkItem.Project.ToLower() != "imercado"
                                                          select WorkItem;
            
            this.SetDeveloperOfEachTask(CodeReviewReturns,true);
            this.SetDeveloperOfEachTask(DemandsWithoutCodeReview, false);

            this.CountLeadersDelay();
            this.CountLeadersCodeReview();
            
            this.View.ExibirCodeReview(CodeReviewReturns, DemandsWithoutCodeReview);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="demandCollection"></param>
        /// <returns></returns>
        private List<DemandModel> CheckDaysLate(List<DemandModel> demandCollection) 
        {
            foreach (DemandModel Demanda in demandCollection)
            {
                int DaysPast;

                if (Demanda.Conclude.HasValue)
                {
                    DaysPast = ((TimeSpan)Demanda.Conclude.Value.Subtract(Demanda.EstimatedConclude.Value)).Days;
                }
                else
                {
                    DaysPast = ((TimeSpan)DateTime.Now.Subtract(Demanda.EstimatedConclude.Value)).Days;
                }
                
                for (int i = 0; i < DaysPast; i++)
                {
                    if ((Demanda.EstimatedConclude.Value.AddDays(i)).DayOfWeek != DayOfWeek.Saturday && (Demanda.EstimatedConclude.Value.AddDays(i)).DayOfWeek != DayOfWeek.Sunday)
                    {
                        Demanda.DaysPast++;
                    }
                }
            }
            
            return demandCollection;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="demandCollection"></param>
        private void CreateLinksToLateItens(List<DemandModel> demandCollection)
        {
            foreach (DemandModel Demand in demandCollection)
            {
                Demand.ActiveControlUrL = string.Format(this.LateItemsURL, Demand.ID);
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (this.DemandList != null) this.DemandList.Clear();
            if (this.DemandListOutOfDate != null) this.DemandListOutOfDate.Clear();
            this.DemandList = null;
            this.DemandListOutOfDate = null;
            GC.SuppressFinalize(this);
            GC.WaitForPendingFinalizers();
        }

        #endregion

        #region Verificar utilizade

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="team"></param>
        ///// <returns></returns>
        //private string GetURLTeam(string team)
        //{
        //    switch (team)
        //    {
        //        case "TDI01":
        //            return "Reunião%20Core";
        //        case "TDI02":
        //            return "ReuniaoTDI02";
        //        case "TDI03":
        //            return "Reunião%20Scarface";
        //        default:
        //            throw new Exception("URL Team Not Found");
        //    }
        //}

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="team"></param>
        ///// <returns></returns>
        //private string GetViewActiveControlTeam(string team)
        //{
        //    switch (team)
        //    {
        //        case "TDI01":
        //            return "%7b7F4B93CA%2d188D%2d4285%2dA3AB%2dD8AC4D3BE1AE%7d";
        //        case "TDI02":
        //            return "%7b13E113C0%2d6745%2d4357%2dA7C6%2dFAE8163AFB91%7d";
        //        case "TDI03":
        //            return "%7b2D64F7CB%2d497E%2d4579%2dA423%2d6E71A31EDB10%7d";
        //        default:
        //            throw new Exception("ViewActiveControl Team Not Found");

        //    }
        //}

        #endregion

        public List<DateTime> getFeriados()
        {
            return ConfigManager.GetFeriados();
        }

        public void RetornaListaDisp()
        {
            this.GetListaDispFromServer();

            List<DateTime> fer = this.getFeriados();

            this.View.ExibirListaDisp(ListaDisp, this.Developers, fer);
        }

        //private void GetListaAusencias()
        //{
        //    if (modelAusencias == null)
        //    {
        //        modelAusencias = XMLDemandAccess.GetAusenciasFromXML(ConfigManager.GetAusenciasXMLPath());
        //    }
        //}

        private void GetListaDispFromServer()
        {
            if (this.ListaDisp == null)
            {
                this.ListaDisp = XMLDemandAccess.GetDemandCollectionFromXML(ConfigManager.GetWIGeraDispXMLPath());
                this.DemandListLastUpdate = XMLDemandAccess.GetFileDate(PathToXmlFileDemands);
            }            
        }

        private void GetPrevisaoAlocacaoFromServer()
        {
            if (this.PrevisaoAlocacao == null)
            {
                this.PrevisaoAlocacao = XMLDemandAccess.GetDemandCollectionFromXML(ConfigManager.GetPrevisaoAlocacaoXMLPath());
                this.DemandListLastUpdate = XMLDemandAccess.GetFileDate(PathToXmlFileDemands);
            }            
        }


        public void GeneratefactoryProductionList(FiltroFabrica filtroFabrica, FiltroProjeto filtroProjeto, string requestingUser)
        {
            bool AllowsShow = this.CheckPermission(requestingUser);

            List<BillingModel> Billing = new List<BillingModel>();

            this.GetDemandListFromServer();

            List<DemandModel> AllTasks = (from Task in this.DemandList
                                          where Task.State == "Em Codificacao"
                                          && !(Task.AssignedTo.Equals("Ubiratan Radanovic Vieira"))
                                          select Task).ToList<DemandModel>();

            if (AllowsShow)
            {
                #region Se tiver permissão monta o Faturamento

                foreach (DemandModel Task in AllTasks)
                {
                    BillingModel BillingItem = new BillingModel();
                    DeveloperModel Developer = this.FindDeveloperOf(Task.Revision);

                    if (Developer != null)
                    {
                        BillingItem.Task = Task.ID + " - " + Task.Title;
                        BillingItem.Project = Task.Project;
                        BillingItem.Factory = Developer.DeveloperName.GetFactory(this.Developers);
                        BillingItem.Hourly = Developer.VH;
                        BillingItem.PredictedHours = Task.EstimatedHours;
                        BillingItem.UsedHours = Task.UsedHours;
                        BillingItem.UsedValue = BillingItem.Hourly * BillingItem.UsedHours;
                        //
                        if (BillingItem.Hourly == 50)
                        {
                            BillingItem.EstimatedValue = 52.63M * BillingItem.PredictedHours;
                            BillingItem.UsedValue = 52.63M * BillingItem.UsedHours;
                        }
                        else
                        {
                            BillingItem.EstimatedValue = BillingItem.Hourly * BillingItem.PredictedHours;
                            BillingItem.UsedValue = BillingItem.Hourly * BillingItem.UsedHours;
                        }
                        //
                        BillingItem.State = Task.State;
                        BillingItem.EstimatedStart = Task.EstimatedStart;
                        BillingItem.EstimatedConclude = Task.EstimatedConclude;

                        Billing.Add(BillingItem);
                    }
                }

                #endregion
            }
            else
            {
                #region Se não tiver não monta o Faturamento

                foreach (DemandModel Task in AllTasks)
                {
                    BillingModel BillingItem = new BillingModel();
                    DeveloperModel Developer = this.FindDeveloperOf(Task.Revision);

                    if (Developer != null)
                    {
                        BillingItem.Task = Task.ID + " - " + Task.Title;
                        BillingItem.Project = Task.Project;

                        if (Developer != null)
                            BillingItem.Factory = Developer.DeveloperName.GetFactory(this.Developers);
                        else
                            BillingItem.Factory = "cdsb";

                        BillingItem.PredictedHours = Task.EstimatedHours;
                        BillingItem.UsedHours = Task.UsedHours;

                        BillingItem.State = Task.State;
                        BillingItem.EstimatedStart = Task.EstimatedStart;
                        BillingItem.EstimatedConclude = Task.EstimatedConclude;

                        Billing.Add(BillingItem);
                    }
                }

                #endregion
            }

            Billing = (from BillingItem in Billing where BillingItem.Factory.CheckFilterFactory(filtroFabrica) && BillingItem.Project.CheckFilterProject(filtroProjeto) select BillingItem).ToList<BillingModel>();

            this.TotalBilling(Billing);

            this.View.ExibirFactoryProductionList(Billing, AllowsShow);
        }

        public void ListarSolicitacoes()
        {
            if (this.SolicitacoesSites == null)
            {
                this.SolicitacoesSites = XMLDemandAccess.GetDemandCollectionFromXML(ConfigManager.GetSolicitacoesSitesXMLPath());
                this.SolicitacoesSitesLastUpdate = XMLDemandAccess.GetFileDate(PathToXmlfileSolicitacoesSites);
            }
            
            //Aplicar filtros
            List<DemandModel> listaView = (from Task in this.SolicitacoesSites
                                          where Task.Title.ToLower().StartsWith("dt") && Task.State != "Cancelado"
                                          select Task).ToList<DemandModel>();

            //Devolver para View
            this.View.ExibirSolicitacoesSites(listaView);

        }

        public void ListManagementTeamTasks()
        {
            if (this.ManagementTeamTasks == null)
            {
                this.ManagementTeamTasks = XMLDemandAccess.GetDemandCollectionFromXML(ConfigManager.GetManagementTeamTasksXMLPath());
                this.ManagementTeamTasksLastUpdate = XMLDemandAccess.GetFileDate(PathToXmlfileManagementTeamTasks);
            }

            this.ApplyMatRulesManagement(this.ManagementTeamTasks);

            //Devolver para View
            this.View.ExibirManagementTeamTasks(this.ManagementTeamTasks);

        }

        private void ApplyMatRulesManagement(List<DemandModel> workItems)
        {
            DateTime DayAfter = DateTime.Now.GetdaysAfter(20);
            DateTime Today = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);

            foreach (DemandModel WorkItem in workItems)
            {
                WorkItem.Responsible = (WorkItem.WorkItemType == "TaskDesenv" || WorkItem.WorkItemType == "Task") ? WorkItem.CreatedBy + " / " + WorkItem.AssignedTo : WorkItem.AssignedTo;
                SetDemandStatusColorManagement(WorkItem, Today, DayAfter);
                VerifyDevelopingOrPlannedMangement(WorkItem, Today);                
            }
        }

        private void VerifyDevelopingOrPlannedMangement(DemandModel workItem, DateTime today)
        {
            CheckPlanningtaskManagement(workItem);            
        }

        private void CheckPlanningtaskManagement(DemandModel demand)
        {
            if (!demand.EstimatedStart.HasValue && demand.EstimatedConclude.HasValue)
            {
                if (demand.EstimatedHours > DateTime.Now.Date.GetBusinessHoursUntil(demand.EstimatedConclude.Value))
                {
                    demand.PlanningStateImg = ConfigManager.GetErrorIcon();
                    demand.PlanningStateRemarks = "A tarefa já deveria ter o início estimado e ainda não há planejamento.";
                }
                else
                {
                    demand.PlanningStateImg = ConfigManager.GetAttentionIcon();
                    demand.PlanningStateRemarks = "A tarefa não possui data de início estimado, entretanto ainda há horas úteis suficientes até a data de término estimado.";
                }
            }
            else
                if (demand.EstimatedStart.HasValue && !demand.EstimatedConclude.HasValue)
                {
                    demand.PlanningStateImg = ConfigManager.GetErrorIcon();
                    demand.PlanningStateRemarks = "A tarefa não possui data de fim planejada.";
                }
                else
                    if (!demand.EstimatedStart.HasValue && !demand.EstimatedConclude.HasValue)
                    {
                        demand.PlanningStateImg = ConfigManager.GetErrorIcon();
                        demand.PlanningStateRemarks = "A tarefa não possui planejamento.";
                    }
                    else
                    {
                        //possui os dois valores
                        if (demand.EstimatedHours > demand.EstimatedStart.Value.Date.GetBusinessHoursUntil(demand.EstimatedConclude.Value))
                        {
                            demand.PlanningStateImg = ConfigManager.GetErrorIcon();
                            demand.PlanningStateRemarks = "O prazo da tarefa não possui horas úteis suficientes para seu término.";
                        }
                    }
        }

        private void SetDemandStatusColorManagement(DemandModel workItem, DateTime today, DateTime dayAfter)
        {
            // Se está com inicio atrasado
            if (workItem.EstimatedStart <= today)
            {
                workItem.StatusColor = LATE;
            }
            // Se começa amanhã
            else if (workItem.EstimatedStart == today.AddDays(1))
            {
                workItem.StatusColor = DEADLINE;
            }
            // Se está a no máximo 3 dias do inicio
            else if (workItem.EstimatedStart <= dayAfter)
            {
                workItem.StatusColor = DEADLINECOMING;
            }
            // Sem Data de inicio Definida
            else if (workItem.EstimatedStart == null)
            {
                workItem.StatusColor = NONE;
            }
            // No Prazo
            else
            {
                workItem.StatusColor = AWAY;
            }
        }

        public void ListarScenariosAndTasks()
        {
            if (this.ScenariosAndTasks == null)
            {
                this.ScenariosAndTasks = XMLDemandAccess.GetScenariosAndTasksFromXML(ConfigManager.GetWIScenariosAndTasksXMLPath());
                this.ScenariosAndTasksLastUpdate = XMLDemandAccess.GetFileDate(WIScenariosAndTasksXMLPath);
            }
            
            //Devolver para View
            this.View.ExibirScenariosAndTasks(ScenariosAndTasks);

        }
    }
}
